package com.hontech.pastacooking.conn

import com.hontech.pastacooking.except.AckException
import com.hontech.pastacooking.serial.ByteView
import com.hontech.pastacooking.serial.SerialType
import com.hontech.pastacooking.serial.UInt16
import com.hontech.pastacooking.serial.UInt8
import com.hontech.pastacooking.utils.S
import java.io.IOException

suspend fun requestMain(timeout: Long, req: Int, args: Array<SerialType>, exceptMsg: String) {
    Device.request(timeout, Addr.Main, req, args, exceptMsg)
}

suspend fun setCleanParam(c: Int, waterVolume: Int, d: Int, steamTime: Int, duration: Int) {
    val timeout = 5 * 1000L
    Device.request(
        timeout,
        Addr.Main,
        MainProto.SetCleanParam,
        arrayOf(UInt16(c), UInt16(waterVolume), UInt16(d), UInt16(steamTime), UInt16(duration)),
        S.t251
    )
}

suspend fun testPick(col: Int, row: Int) {
    val timeout = 180 * 1000L
    Device.request(
        timeout,
        Addr.Main,
        MainProto.TestPick,
        arrayOf(UInt8(col), UInt8(row)),
        S.t252
    )
}

suspend fun testScanner(): String {
    val timeout = 5 * 1000L
    val frame = Device.send(
        timeout,
        Addr.Main,
        MainProto.TestScanner,
        arrayOf()
    )
    val ec = UInt8()
    val bw = ByteView()
    frame.parse(ec, bw)
    if (!ec.isOk()) {
        throw IOException("${S.t253}:${MainProto.errMsg(ec.value)}")
    }
    return bw.toString()
}

suspend fun scan() {

    mainPreProc()

    val timeout = 600 * 1000L
    Device.request(
        timeout,
        Addr.Main,
        MainProto.Scan,
        arrayOf(),
        S.t254
    )
}

class CleanParam(
    val c: Int,
    val waterVolume: Int,
    val d: Int,
    val steamTime: Int
)

class CleanParam2(
    val c: Int,
    val waterVolume: Int,
    val d: Int,
    val steamTime: Int,
    val duration: Int
)

suspend fun mainPreProc() {

    for (i in 0 until 3) {

        try {
            Device.request(
                3000,
                Addr.Main,
                MainProto.PreProc,
                arrayOf(),
                S.t255
            )
            return
        } catch (e: AckException) {
            e.printStackTrace()
        }
    }

    throw IOException(S.t256)
}

suspend fun queryCleanParam(): CleanParam2 {
    val timeout = 3 * 1000L
    val frame = Device.send(
        timeout,
        Addr.Main,
        MainProto.QueryCleanParam,
        arrayOf()
    )
    val c = UInt16()
    val waterVolume = UInt16()
    val d = UInt16()
    val steamTime = UInt16()
    val duration = UInt16()
    frame.parse(c, waterVolume, d, steamTime, duration)
    return CleanParam2(c.value, waterVolume.value, d.value, steamTime.value, duration.value)
}

suspend fun pickupCooking(col: Int, row: Int, cleanOptions: Int, clean: CleanParam, cook: CookingParam) {

    mainPreProc()

    val args: Array<SerialType> = arrayOf(
        UInt8(col), UInt8(row),
      //  UInt8(cleanOptions),
        UInt16(clean.c), UInt16(clean.waterVolume), UInt16(clean.d), UInt16(clean.steamTime),

        UInt16(cook.k), UInt16(cook.preWater), UInt16(cook.f), UInt16(cook.g),
        UInt16(cook.defroze), UInt16(cook.e), UInt16(cook.pourWater),
        UInt16(cook.h), UInt16(cook.mixsoup), UInt16(cook.i),
        UInt16(cook.clogging)
    )

    val timeout = 4 * 60 * 1000L

    for (i in 0 until 3) {
        try {
            Device.request(
                timeout,
                Addr.Main,
                MainProto.PickupCooking,
                args,
                S.t257
            )
            return
        } catch (e: AckException) {
            e.printStackTrace()
        }
    }

    throw IOException(S.t258)
}

suspend fun deviceReset() {
    Device.request(
        60 * 1000L,
        Addr.Main,
        MainProto.DeviceReset,
        arrayOf(),
        S.t259
    )
}

suspend fun ledCtrl(type: Int, value: Int) {
    Device.request(
        3000,
        Addr.Main,
        MainProto.TestLed,
        arrayOf(UInt8(type), UInt8(value)),
        S.t260
    )
}

suspend fun rkcRead(addr: Int): Int {
    val frame = Device.send(
        3000,
        Addr.Main,
        MainProto.RKCRead,
        arrayOf(UInt16(addr))
    )
    val err = UInt8()
    val value = UInt16()
    frame.parse(err, value)
    if (!err.isOk()) {
        throw IllegalStateException(S.t261)
    }
    return value.value
}

suspend fun rkcWrite(addr: Int, value: Int) {
    Device.request(
        3000,
        Addr.Main,
        MainProto.RKCWrite,
        arrayOf(UInt16(addr), UInt16(value)),
        S.t262
    )
}

suspend fun keepAlive() {
    Device.requestKeep(S.t263)
}


const val THAW_CLEAN_ENABLE = 0 // 启用
const val THAW_CLEAN_DISABLE_FOREVER = 1 // 永久禁用
const val THAW_CLEAN_DISABLE = 2 // 禁用1分钟

suspend fun thawCleanCtrl(value: Int) {
    Device.request(
        2000,
        Addr.Main,
        MainProto.BUSYCtrl,
        arrayOf(UInt8(value)),
        "除冰/清洗控制"
    )
}

suspend fun testCooking(col: Int, row: Int) {
    mainPreProc()
    val timeout = 4 * 60 * 1000L
    for (i in 0 until 3) {
        try {
            Device.request(
                timeout,
                Addr.Main,
                MainProto.TestCooking,
                arrayOf(UInt8(col), UInt8(row)),
                "测试出货")
            return
        } catch (e: AckException) {
            e.printStackTrace()
        }
    }
    throw IOException("测试出货失败")
}

